/**********************************************************************
 * DYNAJAX Project [v1.05] - code by Benoit BEGUIN
 * first release: october 2007
 * last update: april 2008
 * Paris, France
 * 
 * DynAjax web site: http://www.dynajax.org/
 * DynAjax samples web site: http://samples.dynajax.org/
 * Any question: mailto:admin@dynajax.org
 * Company support: http://www.odesys.fr
 **********************************************************************/

using System;
using System.IO;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Xml;
using log4net;
using Newtonsoft.Json;

/// <summary>
/// This class generates dynamic Javascript file that permits
/// direct calls to dynAjax aspx handler page
/// </summary>
public partial class javascript_dynAjax : System.Web.UI.Page {
    #region Constants
    private const string PARAM_CONFIG_PATH = "../config/dynAjaxConfig.xml";
    public const string CLASS_ID_PARAM = "classId";
    public const string METHOD_NAME_PARAM = "methodName";
    public const string METHOD_ARGS_PARAM = "methodArgs";
    #endregion

    #region Attributes
    private static ILog logger = log4net.LogManager.GetLogger(typeof(javascript_dynAjax));
    protected static XmlNamespaceManager nsmgr = null;
    protected static XmlDocument configDoc = null;
    protected static DateTime? configFileLastUpdate = null;
    protected string dynamicJsText = "";
    #endregion

    #region Component events
    protected void Page_Load(object sender, EventArgs e) {
        // Set response content type to javascript
        Response.ContentType = "text/javascript";
        // set expiration on page - no cache: put 0
        Response.Expires = 0;

        addDynamicContent();
    }
    #endregion

    #region Private methods
    protected void addDynamicContent() {
        readConfigFile();
        if (configDoc != null) {
            XmlNodeList nodesList = configDoc.DocumentElement.SelectNodes("dynajax:class", nsmgr);
            foreach (XmlNode classNode in nodesList) {
                addClassDefinition(classNode);
            }
        }
    }

    protected void addClassDefinition(XmlNode classNode) {
        string className = classNode.Attributes["id"].Value;
        dynamicJsText += "var " + className + "Class = Class.create();\n";
        dynamicJsText += className + "Class.prototype = {\n";
        dynamicJsText += "  initialize: function() {},\n";

        XmlNodeList nodesList = classNode.SelectNodes("dynajax:method", nsmgr);
        string separator = "";
        foreach (XmlNode methodNode in nodesList) {
            dynamicJsText += separator + "\n";
            addMethodDefinition(className, methodNode);
            separator = ", ";
        }
        dynamicJsText += "\n};\n";
        dynamicJsText += "var " + className + " = new " + className + "Class();\n\n";
    }

    protected void addMethodDefinition(string className, XmlNode methodNode) {
        XmlNodeList paramsList = methodNode.SelectNodes("dynajax:param", nsmgr);
        string paramsListStr = "";
        string separator = "";
        foreach (XmlNode paramNode in paramsList) {
            paramsListStr += separator + paramNode.Attributes["name"].Value;
            separator = ", ";
        }

        string methodName = methodNode.Attributes["name"].Value;
        dynamicJsText += "  " + methodName + ": function(" + paramsListStr + separator + "callBackMethod) {\n";
        dynamicJsText += "    var args = [" + paramsListStr + "];\n";
        dynamicJsText += "    return dynAjaxManager.getDynaData('" + className + "', '" + methodName + "', args, callBackMethod);\n";
        dynamicJsText += "  }";
    }

    protected void readConfigFile() {
        try {
            DateTime lastUpdate = File.GetLastWriteTime(Server.MapPath(PARAM_CONFIG_PATH));
            if (configDoc == null || configFileLastUpdate == null || lastUpdate > configFileLastUpdate) {
                // Read dynAjax config file
                configDoc = new XmlDocument();
                configDoc.Load(Server.MapPath(PARAM_CONFIG_PATH));

                // set XmlNamespaceManager
                nsmgr = new XmlNamespaceManager(configDoc.NameTable);
                nsmgr.AddNamespace("dynajax", configDoc.DocumentElement.NamespaceURI);

                // set config file last update date
                configFileLastUpdate = lastUpdate;
            }
        }
        catch (Exception ex) {
            logger.Error("Failed to load xml config file - return null", ex);
            // If exception, set configDoc to null
            configDoc = null;
        }
    }

    protected object[] constructMethodArgs(XmlNode methodNode, string methodJsonArgs) {
        if (!string.IsNullOrEmpty(methodJsonArgs)) {
            ArrayList argsObject = JavaScriptConvert.DeserializeObject<ArrayList>(methodJsonArgs);
            return ((object[])argsObject.ToArray());
        }
        return new object[] { 1, 1, 1 };
    }
    #endregion
}
